package com.wgz.medicalmanagement.common.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;

/**
 * Redis配置类
 * 优化Redis连接以提高性能和稳定性
 *
 * @author medical
 * @since 2023-05-29
 */
@Slf4j
@Configuration
@EnableAsync
public class RedisConfig {

    /**
     * 配置异步任务执行器
     */
    @Bean
    public Executor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(4);
        executor.setMaxPoolSize(10);
        executor.setQueueCapacity(100);
        executor.setThreadNamePrefix("Redis-Async-");
        executor.initialize();
        return executor;
    }

    /**
     * 配置RedisTemplate
     *
     * @param connectionFactory Redis连接工厂
     * @return RedisTemplate实例
     */
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(connectionFactory);
        
        // 使用StringRedisSerializer来序列化和反序列化redis的key
        template.setKeySerializer(new StringRedisSerializer());
        template.setHashKeySerializer(new StringRedisSerializer());
        
        // 使用GenericJackson2JsonRedisSerializer来序列化和反序列化redis的value值
        GenericJackson2JsonRedisSerializer jsonSerializer = new GenericJackson2JsonRedisSerializer();
        template.setValueSerializer(jsonSerializer);
        template.setHashValueSerializer(jsonSerializer);
        
        template.afterPropertiesSet();
        
        // 预热连接池
        preWarmConnectionPool(template);
        
        return template;
    }
    
    /**
     * 预热Redis连接池，避免首次使用时的延迟
     * 异步执行，不影响应用启动速度
     */
    @Async
    public void preWarmConnectionPool(RedisTemplate<String, Object> redisTemplate) {
        try {
            log.info("预热Redis连接池...");
            // 执行一个简单的ping命令以初始化连接
            redisTemplate.getConnectionFactory().getConnection().ping();
            log.info("Redis连接池预热完成");
        } catch (Exception e) {
            log.warn("Redis连接池预热失败，将在实际使用时建立连接: {}", e.getMessage());
        }
    }
} 